; Simulator model support, plus misc. things associated with a cpu family.
-; Copyright (C) 2000, 2002 Red Hat, Inc.
+; Copyright (C) 2000, 2002, 2003 Red Hat, Inc.
; This file is part of CGEN.
+(define (unit:enum u)
+ (gen-c-symbol (string-append "UNIT_"
+ (string-upcase (obj:name u))))
+)
+
; Return C code to define cpu implementation properties.
(define (-gen-cpu-imp-properties)
)
)
+; Return the name of the class representing the given MODEL.
+(define (gen-model-class-name model)
+ (string-append "@prefix@_" (gen-sym model) "_model")
+)
+
; Return name of profiling handler for MODEL, UNIT.
; Also called by sim.scm.
-(define (gen-model-unit-fn-name model unit)
- (string-append "@prefix@_model_" (gen-sym model) "_" (gen-sym unit))
+(define (gen-model-unit-fn-name model unit when)
+ (string-append "model_" (gen-sym unit) "_" (symbol->string when))
)
-; Return decls of all insn model handlers.
-; This is called from sim-decode.scm.
-
-(define (gen-model-fn-decls)
+(define (gen-model-unit-fn-decl model unit when)
(let ((gen-args (lambda (args)
(gen-c-args (map (lambda (arg)
(string-append
(not (null? (cdr arg))))
args)))))
)
+ (string-append
+ " virtual UINT "
+ (gen-model-unit-fn-name model unit when)
+ " (@cpu@_cpu *cpu, const struct @prefix@_idesc *idesc,"
+ " int unit_num"
+ (if (equal? when 'after)
+ ", unsigned long long referenced" "")
+ (gen-args (unit:inputs unit))
+ (gen-args (unit:outputs unit))
+ ")\n"))
+)
- (string-list
- ; -gen-hw-profile-decls
- "/* Function unit handlers (user written). */\n\n"
- (string-list-map
- (lambda (model)
- (string-list-map (lambda (unit)
- (string-append
- "extern int "
- (gen-model-unit-fn-name model unit)
- " (@cpu@_cpu *, const struct @prefix@_idesc *,"
- " int /*unit_num*/, int /*referenced*/"
- (gen-args (unit:inputs unit))
- (gen-args (unit:outputs unit))
- ");\n"))
- (model:units model)))
- (current-model-list))
- "\n"
- "/* Profiling before/after handlers (user written) */\n\n"
- "extern void @prefix@_model_insn_before (@cpu@_cpu *, int /*first_p*/);\n"
- "extern void @prefix@_model_insn_after (@cpu@_cpu *, int /*last_p*/, int /*cycles*/);\n"
- "\n"
- ))
+; Return decls of all insn model handlers.
+
+(define (gen-model-fn-decls model)
+ (string-list
+ "\n"
+ "// Function unit handlers\n"
+ "// To be overridden as needed.\n"
+ (string-list-map (lambda (unit)
+ (string-append
+ (gen-model-unit-fn-decl model unit 'before)
+ " {\n"
+ " return 0;\n"
+ " }\n"
+ (gen-model-unit-fn-decl model unit 'after)
+ " {\n"
+ " return timing[idesc->sem_index].units[unit_num].done;\n"
+ " }\n"))
+ (model:units model))
+ )
)
; Return name of profile handler for INSN, MODEL.
-(define (-gen-model-insn-fn-name model insn)
- (string-append "model_" (gen-sym model) "_" (gen-sym insn))
+(define (-gen-model-insn-fn-name model insn when)
+ (string-append "model_" (gen-sym insn) "_" (symbol->string when))
+)
+
+(define (-gen-model-insn-qualified-fn-name model insn when)
+ (string-append (gen-model-class-name model) "::" (-gen-model-insn-fn-name model insn when))
+)
+
+; Return declaration of function to model INSN.
+
+(define (-gen-model-insn-fn-decl model insn when)
+ (string-list
+ "UINT "
+ (-gen-model-insn-fn-name model insn when)
+ " (@cpu@_cpu *current_cpu, @prefix@_scache *sem);\n"
+ )
+)
+
+(define (-gen-model-insn-fn-decls model)
+ (string-list
+ " // These methods call the appropriate unit modeller(s) for each insn.\n"
+ (string-list-map
+ (lambda (insn)
+ (string-list
+ " " (-gen-model-insn-fn-decl model insn 'before)
+ " " (-gen-model-insn-fn-decl model insn 'after)))
+ (non-multi-insns (real-insns (current-insn-list))))
+ )
)
; Return function to model INSN.
-(define (-gen-model-insn-fn model insn)
+(define (-gen-model-insn-fn model insn when)
(logit 2 "Processing modeling for " (obj:name insn) ": \"" (insn-syntax insn) "\" ...\n")
(let ((sfmt (insn-sfmt insn)))
(string-list
- "static int\n"
- (-gen-model-insn-fn-name model insn)
- " (@cpu@_cpu *current_cpu, @prefix@_scache *sem_arg)\n"
+ "UINT\n"
+ (-gen-model-insn-qualified-fn-name model insn when)
+ " (@cpu@_cpu *current_cpu, @prefix@_scache *sem)\n"
"{\n"
(if (with-scache?)
(gen-define-field-macro sfmt)
"")
- " const @prefix@_argbuf * UNUSED abuf = sem_arg->argbuf;\n"
- " const @prefix@_idesc * UNUSED idesc = abuf->idesc;\n"
+ " const @prefix@_scache* abuf = sem;\n"
+ " const @prefix@_idesc* idesc = abuf->idesc;\n"
; or: idesc = & CPU_IDESC (current_cpu) ["
; (gen-cpu-insn-enum (mach-cpu (model:mach model)) insn)
; "];\n"
(gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
(gen-sfmt-argvars-assigns sfmt)))
; Emit code to model the insn. Function units are handled here.
- (send insn 'gen-profile-code model "cycles")
+ (send insn 'gen-profile-code model when "cycles")
" return cycles;\n"
(if (with-scache?)
(gen-undef-field-macro sfmt)
"}\n\n"))
)
+
; Return insn modeling handlers.
; ??? Might wish to reduce the amount of output by combining identical cases.
; ??? Modelling of insns could be table driven, but that puts constraints on
"/* Model handlers for each insn. */\n\n"
(lambda () (string-write-map
(lambda (model)
+ (string-write
+ ; Generate the model constructor.
+ (gen-model-class-name model) "::" (gen-model-class-name model) " (@cpu@_cpu *cpu)\n"
+ " : cgen_model (cpu)\n"
+ "{\n"
+ "}\n"
+ "\n")
(string-write-map
- (lambda (insn) (-gen-model-insn-fn model insn))
+ (lambda (insn)
+ (string-list
+ (-gen-model-insn-fn model insn 'before)
+ (-gen-model-insn-fn model insn 'after)))
(non-multi-insns (real-insns (current-insn-list)))))
(current-model-list)))
)
)
+
+(define (-gen-model-class-decls model)
+ (string-append
+ "\n"
+ " "
+ (gen-enum-decl 'unit_number "unit types"
+ "UNIT_"
+ (cons '(none)
+ (append
+ ; "apply append" squeezes out nils.
+ (apply append
+ (list
+ ; create <model_name>-<unit-name> for each unit
+ (let ((units (model:units model)))
+ (if (null? units)
+ nil
+ (map (lambda (unit)
+ (cons (obj:name unit)
+ (cons '- (atlist-attrs (obj-atlist model)))))
+ units)))))
+ '((max)))))
+ " struct unit {\n"
+ " unit_number unit;\n"
+ " UINT issue;\n"
+ " UINT done;\n"
+ " };\n\n"
+
+ ; FIXME: revisit MAX_UNITS
+ " #define MAX_UNITS ("
+ (number->string
+ (let ((insn-list (non-multi-insns (real-insns (current-insn-list)))))
+ (if (null? insn-list)
+ 1
+ (apply max
+ (map (lambda (lengths) (apply max lengths))
+ (map (lambda (insn)
+ (let ((timing (insn-timing insn)))
+ (if (null? timing)
+ '(1)
+ (map (lambda (insn-timing)
+ (length (timing:units (cdr insn-timing))))
+ timing))))
+ insn-list))))))
+ ")\n"
+ )
+)
+
+; Return the C++ class representing the given model.
+(define (gen-model-class model)
+ (string-list
+ "\
+class " (gen-model-class-name model) " : public cgen_model
+{
+public:
+ " (gen-model-class-name model) " (@cpu@_cpu *cpu);
+
+ // Call the proper unit modelling function for the given insn.
+ UINT model_before (@cpu@_cpu *current_cpu, @prefix@_scache* sem)
+ {
+ return (this->*(timing[sem->idesc->sem_index].model_before)) (current_cpu, sem);
+ }
+ UINT model_after (@cpu@_cpu *current_cpu, @prefix@_scache* sem)
+ {
+ return (this->*(timing[sem->idesc->sem_index].model_after)) (current_cpu, sem);
+ }
+"
+ (gen-model-fn-decls model)
+ "\
+
+protected:
+"
+ (-gen-model-insn-fn-decls model)
+ (-gen-model-class-decls model)
+"\
+
+ typedef UINT (" (gen-model-class-name model) "::*model_function) (@cpu@_cpu* current_cpu, @prefix@_scache* sem);
+
+ struct insn_timing {
+ // This is an integer that identifies this insn.
+ UINT num;
+ // Functions to handle insn-specific profiling.
+ model_function model_before;
+ model_function model_after;
+ // Array of function units used by this insn.
+ unit units[MAX_UNITS];
+ };
+
+ static const insn_timing timing[];
+};
+"
+ )
+)
+
+; Return the C++ classes representing the current list of models.
+(define (gen-model-classes)
+ (string-list-map
+ (lambda (model)
+ (string-list
+ "\n"
+ (gen-model-class model)))
+ (current-model-list))
+)
\f
; Generate timing table entry for function unit U while executing INSN.
; U is a <unit> object.
(define (-gen-insn-unit-timing model insn u args)
(string-append
"{ "
- "(int) " (unit:enum u) ", "
+ (gen-model-class-name model) "::" (unit:enum u) ", "
(number->string (unit:issue u)) ", "
(let ((cycles (assq-ref args 'cycles)))
(if cycles
(gen-cpu-insn-enum (mach-cpu (model:mach model)) insn)
", "
(if (obj-has-attr? insn 'VIRTUAL)
- "0"
- (-gen-model-insn-fn-name model insn))
+ "0, 0"
+ (string-append
+ "& " (-gen-model-insn-qualified-fn-name model insn 'before) ", "
+ "& " (-gen-model-insn-qualified-fn-name model insn 'after)))
", { "
(string-drop
-2
(define (-gen-model-timing-table model)
(string-write
"/* Model timing data for `" (obj:name model) "'. */\n\n"
- "static const @PREFIX@_INSN_TIMING " (gen-sym model) "_timing[] = {\n"
+ "const " (gen-model-class-name model) "::insn_timing " (gen-model-class-name model) "::timing[] = {\n"
(lambda () (string-write-map (lambda (insn) (-gen-insn-timing model insn))
(non-multi-insns (non-alias-insns (current-insn-list)))))
"};\n\n"
copyright-red-hat package-red-hat-simulators)
"\
-#include \"@arch@-main.h\"
+#include \"@cpu@.h\"
using namespace @cpu@; // FIXME: namespace organization still wip
/* The profiling data is recorded here, but is accessed via the profiling
mechanism. After all, this is information for profiling. */
-#if WITH_PROFILE_MODEL_P
-
"
-gen-model-insn-fns
-gen-model-profile-data
-"#endif /* WITH_PROFILE_MODEL_P */\n\n"
-
- -gen-model-defns
- -gen-cpu-imp-properties
- -gen-cpu-defns
- -gen-mach-defns
+; not adapted for sid yet
+; -gen-model-defns
+; -gen-cpu-imp-properties
+; -gen-cpu-defns
+; -gen-mach-defns
)
)
+
+(define (cgen-model.h)
+ (logit 1 "Generating " (gen-cpu-name) " model.h ...\n")
+ (assert-keep-one)
+
+ (string-write
+ (gen-copyright "Simulator model support for @prefix@."
+ copyright-red-hat package-red-hat-simulators)
+ "\
+#ifndef @PREFIX@_MODEL_H
+#define @PREFIX@_MODEL_H
+
+#include \"cgen-cpu.h\"
+#include \"cgen-model.h\"
+
+namespace @cpu@
+{
+using namespace cgen;
+"
+ (gen-model-classes)
+ "\
+
+} // namespace @cpu@
+
+#endif // @PREFIX@_MODEL_H
+"
+ )
+)
; Simulator generator support routines.
-; Copyright (C) 2000, 2002 Red Hat, Inc.
+; Copyright (C) 2000, 2002, 2003 Red Hat, Inc.
; This file is part of CGEN.
; One goal of this file is to provide cover functions for all methods.
(method-make!
<operand> 'gen-profile-code
- (lambda (self insn out?)
+ (lambda (self insn when out?)
(string-append " "
"@prefix@_model_mark_"
(if out? "set_" "get_")
(gen-sym (op:type self))
+ "_" when
" (current_cpu"
(if (hw-scalar? (op:type self))
""
(current-model-list))
'((max))))
"#define MAX_MODELS ((int) MODEL_MAX)\n\n"
- (gen-enum-decl 'unit_type "unit types"
- "UNIT_"
- (cons '(none)
- (append
- ; "apply append" squeezes out nils.
- (apply append
- ; create <model_name>-<unit-name> for each unit
- (map (lambda (model)
- (let ((units (model:units model)))
- (if (null? units)
- nil
- (map (lambda (unit)
- (cons (symbol-append (obj:name model) '-
- (obj:name unit))
- (cons '- (atlist-attrs (obj-atlist model)))))
- units))))
- (current-model-list)))
- '((max)))))
- ; FIXME: revisit MAX_UNITS
- "#define MAX_UNITS ("
- (number->string
- (apply max
- (map (lambda (lengths) (apply max lengths))
- (map (lambda (insn)
- (let ((timing (insn-timing insn)))
- (if (null? timing)
- '(1)
- (map (lambda (insn-timing)
- (length (timing:units (cdr insn-timing))))
- timing))))
- (non-multi-insns (real-insns (current-insn-list)))))))
- ")\n\n"
- )
+ )
)
\f
; Function units.
(method-make!
<unit> 'gen-profile-code
- (lambda (self unit-num insn overrides cycles-var-name)
+ (lambda (self unit-num insn when overrides cycles-var-name)
+ (logit 3 " 'gen-profile-code\n")
(let (
(inputs (unit:inputs self))
(outputs (unit:outputs self))
; UNIT-REFERENCED-VAR.
; ??? For now we assume all input operands are read.
(gen-ref-arg (lambda (arg num in-out)
+ (logit 3 " gen-ref-arg\n")
(let* ((op-name (assq-ref overrides (car arg)))
(op (insn-op-lookup (if op-name
(car op-name)
; Initialize unit argument ARG.
; OUT? is #f for input args, #t for output args.
(gen-arg-init (lambda (arg out?)
+ (logit 3 " gen-arg-unit\n")
(if (or
; Ignore scalars.
(null? (cdr arg))
; Return C code to declare variable to hold unit argument ARG.
; OUT? is #f for input args, #t for output args.
(gen-arg-decl (lambda (arg out?)
+ (logit 3 " gen-arg-decl " arg out? "\n")
(if (null? (cdr arg)) ; ignore scalars
""
(string-append " "
; Return C code to pass unit argument ARG to the handler.
; OUT? is #f for input args, #t for output args.
(gen-arg-arg (lambda (arg out?)
+ (logit 3 " gen-arg-arg\n")
(if (null? (cdr arg)) ; ignore scalars
""
(string-append ", "
(string-append
" {\n"
- " int referenced = 0;\n"
- " unsigned long long UNUSED insn_referenced = abuf->written;\n"
+ (if (equal? when 'after)
+ (string-append
+ " int referenced = 0;\n"
+ " unsigned long long insn_referenced = abuf->written;\n")
+ "")
; Declare variables to hold unit arguments.
(string-map (lambda (arg) (gen-arg-decl arg #f))
inputs)
"invalid spec" arg))))
overrides)
; Create bitmask indicating which args were referenced.
- (string-map (lambda (arg num) (gen-ref-arg arg num 'in))
- inputs
- (iota (length inputs)))
- (string-map (lambda (arg num) (gen-ref-arg arg num 'out))
- outputs
- (iota (length inputs)
- (length outputs)))
+ (if (equal? when 'after)
+ (string-append
+ (string-map (lambda (arg num) (gen-ref-arg arg num 'in))
+ inputs
+ (iota (length inputs)))
+ (string-map (lambda (arg num) (gen-ref-arg arg num 'out))
+ outputs
+ (iota (length inputs)
+ (length outputs))))
+ "")
; Emit the call to the handler.
" " cycles-var-name " += "
- (gen-model-unit-fn-name (unit:model self) self)
- " (current_cpu, abuf->idesc"
+ (gen-model-unit-fn-name (unit:model self) self when)
+ " (current_cpu, idesc"
", " (number->string unit-num)
- ", referenced"
+ (if (equal? when 'after) ", referenced" "")
(string-map (lambda (arg) (gen-arg-arg arg #f))
inputs)
(string-map (lambda (arg) (gen-arg-arg arg #t))
(method-make!
<iunit> 'gen-profile-code
- (lambda (self unit-num insn cycles-var-name)
+ (lambda (self unit-num insn when cycles-var-name)
(let ((args (iunit:args self))
(unit (iunit:unit self)))
- (send unit 'gen-profile-code unit-num insn args cycles-var-name)))
+ (send unit 'gen-profile-code unit-num insn when args cycles-var-name)))
)
\f
; Mode support.
(method-make!
<insn> 'gen-profile-code
- (lambda (self model cycles-var-name)
+ (lambda (self model when cycles-var-name)
(string-append
(let ((timing (assq-ref (insn-timing self) (obj:name model))))
(if timing
(string-map (lambda (iunit unit-num)
- (send iunit 'gen-profile-code unit-num self cycles-var-name))
+ (send iunit 'gen-profile-code unit-num self when cycles-var-name))
(timing:units timing)
(iota (length (timing:units timing))))
- (send (model-default-unit model) 'gen-profile-code 0 self nil cycles-var-name)))
+ (send (model-default-unit model) 'gen-profile-code 0 self when nil cycles-var-name)))
))
)
\f