diff --git a/lib/ADL/base.rb b/lib/ADL/base.rb index 4eb5910..469dd62 100644 --- a/lib/ADL/base.rb +++ b/lib/ADL/base.rb @@ -4,6 +4,10 @@ module SimInfra # @@instructions -array of instruction description # shows result of our tests in interactive Ruby (IRB) or standalone + @@regfiles = [] unless defined?(@@regfiles) + @@interface_functions = [] unless defined?(@@interface_functions) + @@instructions = [] unless defined?(@@instructions) + def self.serialize(msg= nil) require 'yaml' yaml_data = YAML.dump( @@ -17,7 +21,7 @@ def self.serialize(msg= nil) end def self.state - yaml_data = YAML.dump( + YAML.dump( { regfiles: @@regfiles.map(&:to_h), interface_functions: @@interface_functions.map(&:to_h), diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index 9c31471..6525f98 100644 --- a/lib/ADL/builder.rb +++ b/lib/ADL/builder.rb @@ -29,7 +29,7 @@ def self.from_h(h) end # Basics -module SimInfra +module SimInfra def assert(condition, msg = nil); raise msg if !condition; end @@instructions = [] @@ -53,9 +53,9 @@ def to_h fields: @fields.map { |f| f.to_h }, frmt: @frmt, asm_str: @asm_str, + feature: @feature, code: @code.to_h, map: @map.to_h, - feature: @feature, } end @@ -75,15 +75,16 @@ def self.from_h(h) class InstructionInfoBuilder include SimInfra - def initialize(name, feature) - @info = InstructionInfo.new(name, feature) - @info.code = Scope.new(nil) + def initialize(name, feature) + @info = InstructionInfo.new(name, feature) + @info.code = Scope.new(nil) @@interface_functions.each do |func| + next if func[:kind] == :memory if !func[:return_types].empty? @info.code.instance_eval "def #{func[:name]}(*args) in_s = *args.map { |a| resolve_const(a) } - in_stmt = [tmpvar(#{func[:return_types][0]})] + in_stmt = [tmpvar(#{func[:return_types][0]})] in_stmt.concat(in_s) return stmt :#{func[:name]}, in_stmt end @@ -101,10 +102,10 @@ def initialize(name, feature) end def encoding(frmt, fields, *args) - @info.fields = fields - @info.frmt= frmt - map args - + @info.fields = fields + @info.frmt= frmt + map args + sum_bits = 0 for f in fields sum_bits += Utility.get_type(f.value.type).bitsize @@ -125,14 +126,19 @@ def Instruction(name, &block) class InterfaceBuilder include SimInfra - def Function(name, output_types = [], input_types = []) - @@interface_functions << {:name => name, :return_types => output_types, :argument_types => input_types} + def Function(name, return_types: [], argument_types: [], attrs: [], kind: nil) + @@interface_functions << { + name: name, + return_types: return_types, + argument_types: argument_types, + attrs: attrs, + kind: kind, + } end end def Interface(&blck) bldr = InterfaceBuilder.new() - bldr.instance_eval &blck end @@ -176,27 +182,27 @@ def self.from_h(h) end @@regfiles = [] -class RegisterFileBuilder - attr_reader :info - - def initialize(name) - @info = RegisterFileInfo.new(name) - @info.regs = [] - end - - def method_missing(name, *args) - if name.to_s.start_with?('r') - size = name.to_s[1..].to_i - instance_eval "def #{name}(sym, *args); @info.regs << Register.new(sym, #{size}, args.size > 0 ? args : []); end", __FILE__, __LINE__ - @info.regs << Register.new(args[0], size, args.size > 1 ? args[1..] : []) - else - error "Unknown method #{name}" + class RegisterFileBuilder + attr_reader :info + + def initialize(name) + @info = RegisterFileInfo.new(name) + @info.regs = [] + end + + def method_missing(name, *args) + if name.to_s.start_with?('r') + size = name.to_s[1..].to_i + instance_eval "def #{name}(sym, *args); @info.regs << Register.new(sym, #{size}, args.size > 0 ? args : []); end", __FILE__, __LINE__ + @info.regs << Register.new(args[0], size, args.size > 1 ? args[1..] : []) + else + error "Unknown method #{name}" + end + end + + def zero = :zero + def pc = :pc end - end - - def zero = :zero - def pc = :pc -end def RegisterFile(name, &block) bldr = RegisterFileBuilder.new(name) diff --git a/lib/ADL/scope.rb b/lib/ADL/scope.rb index 2175a7e..1c82fc3 100644 --- a/lib/ADL/scope.rb +++ b/lib/ADL/scope.rb @@ -106,8 +106,27 @@ def zext(a, type) = stmt(:zext, [tmpvar(type), a]) def get_reg(expr, regset, type) = rlet("_reg_#{next_counter}".to_sym, regset, type, expr) def write(rfile, reg, expr) = stmt(:write, [rfile, reg, expr]) - def writeMem(addr, expr) = stmt(:writeMem, [addr, expr]) - def readMem(addr, type) = stmt(:readMem, [tmpvar(type), addr]) + + def writeMem(addr, expr) + iface = @@interface_functions.find do |f| + f[:kind] == :memory && + f[:name].to_s.start_with?('writeMem') && + f[:argument_types] == [addr.type, expr.type] + end + raise "no memory interface declared for writeMem of #{expr.type}" unless iface + stmt(:writeMem, [addr, expr], iface[:name]) + end + + def readMem(addr, type) + iface = @@interface_functions.find do |f| + f[:kind] == :memory && + f[:name].to_s.start_with?('readMem') && + f[:return_types] == [type] + end + raise "no memory interface declared for readMem of #{type}" unless iface + v = tmpvar(type) + stmt(:readMem, [v, addr], iface[:name]) + end def read(rfile, reg) v = tmpvar(:b32) diff --git a/lib/Target/RISC-V/32I.rb b/lib/Target/RISC-V/32I.rb index 95523dd..890ac1a 100644 --- a/lib/Target/RISC-V/32I.rb +++ b/lib/Target/RISC-V/32I.rb @@ -7,7 +7,13 @@ module RV32I extend SimInfra Interface { - Function(:sysCall) + Function(:sysCall, kind: :cpu) + Function(:readMem8, return_types: [:b8], argument_types: [:b32], kind: :memory) + Function(:readMem16, return_types: [:b16], argument_types: [:b32], kind: :memory) + Function(:readMem32, return_types: [:b32], argument_types: [:b32], kind: :memory) + Function(:writeMem8, argument_types: [:b32, :b8], kind: :memory) + Function(:writeMem16, argument_types: [:b32, :b16], kind: :memory) + Function(:writeMem32, argument_types: [:b32, :r32], kind: :memory) } RegisterFile(:XRegs) { diff --git a/sim_gen/CPUState/cpu_state.rb b/sim_gen/CPUState/cpu_state.rb index f7d97c1..820620f 100644 --- a/sim_gen/CPUState/cpu_state.rb +++ b/sim_gen/CPUState/cpu_state.rb @@ -164,7 +164,7 @@ module SimGen module CPUState module Header module_function - + def generate_cpu_state(input_ir) pc_decl = Helper.generate_pc_decl(input_ir[:regfiles]) pc_functions = Helper.generate_pc_functions(input_ir[:regfiles]) diff --git a/sim_lib/Target/RISCV/cpu_state_ext.cc b/sim_lib/Target/RISCV/cpu_state_ext.cc index 4389d9e..1140fc3 100644 --- a/sim_lib/Target/RISCV/cpu_state_ext.cc +++ b/sim_lib/Target/RISCV/cpu_state_ext.cc @@ -1,4 +1,5 @@ #include "cpu_state.hh" +#include namespace prot::state { @@ -13,4 +14,26 @@ void CPU::sysCall() { } } +void CPU::writeMem8(uint32_t addr, uint8_t value) { + m_memory->write(addr, value); +} + +void CPU::writeMem16(uint32_t addr, uint16_t value) { + m_memory->write(addr, value); +} + +void CPU::writeMem32(uint32_t addr, uint32_t value) { + m_memory->write(addr, value); +} + +uint8_t CPU::readMem8(uint32_t addr) { return m_memory->read(addr); } + +uint16_t CPU::readMem16(uint32_t addr) { + return m_memory->read(addr); +} + +uint32_t CPU::readMem32(uint32_t addr) { + return m_memory->read(addr); +} + } // namespace prot::state