From 72e479368b573ce3d0673be67737825627ac92bf Mon Sep 17 00:00:00 2001 From: uslstenn Date: Thu, 11 Jun 2026 19:53:57 +0300 Subject: [PATCH 1/7] [RV32I] Shift (I type) instructions enc upd --- lib/Target/RISC-V/32I.rb | 10 +++++----- lib/Target/RISC-V/encoding.rb | 11 +++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/Target/RISC-V/32I.rb b/lib/Target/RISC-V/32I.rb index 95523dd..9867e56 100644 --- a/lib/Target/RISC-V/32I.rb +++ b/lib/Target/RISC-V/32I.rb @@ -158,19 +158,19 @@ module RV32I } Instruction(:slli) { - encoding *format_i_shift(0b0010011, 0b001, 0b00000) + encoding *format_i_shift(0b0010011, 0b001, 0b0000000) asm { "slli {rd}, {rs1}, {imm}" } code { rd[]= rs1 << imm } } Instruction(:srli) { - encoding *format_i_shift(0b0010011, 0b101, 0b00000) + encoding *format_i_shift(0b0010011, 0b101, 0b0000000) asm { "srli {rd}, {rs1}, {imm}" } code { rd[]= rs1 >> imm } } Instruction(:srai) { - encoding *format_i_shift(0b0010011, 0b101, 0b01000) + encoding *format_i_shift(0b0010011, 0b101, 0b0100000) asm { "srai {rd}, {rs1}, {imm}" } code { rd[]= rs1.s >> imm } } @@ -220,7 +220,7 @@ module RV32I Instruction(:jalr) { encoding *format_i(0b1100111, 0b000) asm { "jalr {rd}, {rs1}, {imm}" } - code { + code { let :t, :b32, pc + 4 branch((rs1 + imm) & (~1)) rd[]= t @@ -262,7 +262,7 @@ module RV32I asm { "lw {rd}, {imm}({rs1})" } code { rd[]= mem[rs1 + imm, :b32] } } - + Instruction(:lbu) { encoding *format_i(0b0000011, 0b100) asm { "lbu {rd}, {imm}({rs1})" } diff --git a/lib/Target/RISC-V/encoding.rb b/lib/Target/RISC-V/encoding.rb index 5ff0310..3214a0b 100644 --- a/lib/Target/RISC-V/encoding.rb +++ b/lib/Target/RISC-V/encoding.rb @@ -60,15 +60,14 @@ def format_i(opcode, funct3) ], i_imm(:imm), xreg(:rs1), xreg(:rd) end - def format_i_shift(opcode, func3, sopcode) - return :srai, [ + def format_i_shift(opcode, func3, funct7) + return :I, [ field(:f_opcode, 6, 0, opcode), - field(:func3, 14, 12, func3), - field(:f_imm4_0, 24, 20), field(:f_rd, 11, 7), + field(:f_funct3, 14, 12, func3), field(:f_rs1, 19, 15), - field(:f_temp, 26, 25, 0b01), - field(:f_sopcode, 31, 27, sopcode), + field(:f_imm11_5, 31, 25, funct7), + field(:f_imm4_0, 24, 20), ], is_imm(:imm), xreg(:rs1), xreg(:rd) end From aa9e5bb299e4092dee0ac0d7fb5f3aef523d83f4 Mon Sep 17 00:00:00 2001 From: uslstenn Date: Tue, 16 Jun 2026 14:46:22 +0300 Subject: [PATCH 2/7] [ADL] Introduced Operands List & Mapping * In addition to the previous map section, we propose ordered operand list with specific map sections per-operand --- lib/ADL/builder.rb | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index 9c31471..54adc12 100644 --- a/lib/ADL/builder.rb +++ b/lib/ADL/builder.rb @@ -40,11 +40,14 @@ def self.interface_functions end class InstructionInfo - attr_accessor :name, :fields, :frmt, :map, :code, :map_code_blocks, :asm_str, :feature + attr_accessor :name, :fields, :frmt, :map, :code, :map_code_blocks, :asm_str, :feature, + :operand_map, :operand_list def initialize(name, feature) @name = name; @map_code_blocks = {} @feature = feature + @operand_map = {} + @operand_list = [] end def to_h @@ -55,6 +58,8 @@ def to_h asm_str: @asm_str, code: @code.to_h, map: @map.to_h, + operand_map: @operand_map.transform_values(&:to_h), + operand_list: @operand_list, feature: @feature, } end @@ -68,6 +73,10 @@ def self.from_h(h) info.code.instance_variable_set(:@tree, h[:code][:tree].map { |s| IrStmt.from_h(s) }) info.map = Scope.new(nil) info.map.instance_variable_set(:@tree, h[:map][:tree].map { |s| IrStmt.from_h(s) }) + if h[:operand_map] + info.operand_map = h[:operand_map].transform_values { |v| Scope.from_h(v) } + info.operand_list = h[:operand_list] || info.operand_map.keys + end info end end @@ -214,17 +223,20 @@ def RegFiles() module SimInfra class InstructionInfoBuilder def code(&block) - if !@info.map_code_blocks.empty? - @info.fields.each { |f| - @info.map.method(f.value.name, f.value.type) - } - end - @info.map_code_blocks.each do |k, v| - @info.map.instance_eval v[1] + # Build legacy map from operand scopes for backward compat + @info.map = Scope.new(nil) + @info.fields.each { |f| @info.map.method(f.value.name, f.value.type) } + @info.operand_map.each_value do |scope| + scope.tree.each { |stmt| @info.map.tree << stmt } end - @info.map_code_blocks.each do |k, v| - @info.code.method(k, v[0], @info.map.vars[k].regset) + + # Link code scope methods to operand vars + @info.operand_map.each do |name, scope| + var = scope.vars[name] + @info.code.method(name, var.type, var.regset) if var end + + # Register files for regfile in @@regfiles for reg in regfile.regs @info.code.method(reg.name, ('r' + reg.size.to_s).to_sym) @@ -234,11 +246,14 @@ def code(&block) end def map(blocks) - if (!blocks.nil? && !blocks.empty?) - for blck in blocks - @info.map_code_blocks[blck[0]] = [blck[1], blck[2]] - end + return if blocks.nil? || blocks.empty? + blocks.each do |name, type, code_str| + scope = Scope.new(nil) + @info.fields.each { |f| scope.method(f.value.name, f.value.type) } + scope.instance_eval(code_str) + @info.operand_map[name] = scope end + @info.operand_list = blocks.map(&:first) end def asm(&block) From 1173e62d462697569416b43af58a48d327acce2e Mon Sep 17 00:00:00 2001 From: uslstenn Date: Tue, 16 Jun 2026 17:25:46 +0300 Subject: [PATCH 3/7] [ADL, simgen] Single :map section is deprecated --- lib/ADL/builder.rb | 10 ---------- sim_gen/Decoders/decoder.rb | 12 ++++-------- sim_gen/ExecEngines/naive_interpreter.rb | 8 ++------ sim_gen/ISA/isa.rb | 22 ++++++++++++++-------- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index 54adc12..81e8aaf 100644 --- a/lib/ADL/builder.rb +++ b/lib/ADL/builder.rb @@ -57,7 +57,6 @@ def to_h frmt: @frmt, asm_str: @asm_str, code: @code.to_h, - map: @map.to_h, operand_map: @operand_map.transform_values(&:to_h), operand_list: @operand_list, feature: @feature, @@ -71,8 +70,6 @@ def self.from_h(h) info.asm_str = h[:asm_str] info.code = Scope.new(nil) info.code.instance_variable_set(:@tree, h[:code][:tree].map { |s| IrStmt.from_h(s) }) - info.map = Scope.new(nil) - info.map.instance_variable_set(:@tree, h[:map][:tree].map { |s| IrStmt.from_h(s) }) if h[:operand_map] info.operand_map = h[:operand_map].transform_values { |v| Scope.from_h(v) } info.operand_list = h[:operand_list] || info.operand_map.keys @@ -223,13 +220,6 @@ def RegFiles() module SimInfra class InstructionInfoBuilder def code(&block) - # Build legacy map from operand scopes for backward compat - @info.map = Scope.new(nil) - @info.fields.each { |f| @info.map.method(f.value.name, f.value.type) } - @info.operand_map.each_value do |scope| - scope.tree.each { |stmt| @info.map.tree << stmt } - end - # Link code scope methods to operand vars @info.operand_map.each do |name, scope| var = scope.vars[name] diff --git a/sim_gen/Decoders/decoder.rb b/sim_gen/Decoders/decoder.rb index c9475d0..e8c28f9 100644 --- a/sim_gen/Decoders/decoder.rb +++ b/sim_gen/Decoders/decoder.rb @@ -157,12 +157,8 @@ def make_child_tree(node_value, separ_mask, instructions, subtree) def map_operands(insn) operands = {} - cnt = 0 - for node in insn[:map][:tree] - if node[:name] == :new_var && !node[:attrs].nil? && node[:attrs].include?(:op) - operands[node[:oprnds][0][:name]] = "insn.operand#{cnt}" - cnt += 1 - end + (insn[:operand_list] || []).each_with_index do |name, idx| + operands[name] = "insn.operand#{idx}" end operands end @@ -189,8 +185,8 @@ def generate_mapping_body(insn) emitter = Utility::GenEmitter.new operand_map = map_operands(insn) gen = CodeGen::CppGenerator.new(emitter, operand_map) - for node in insn[:map][:tree] - gen.generate_statement(node) + (insn[:operand_map] || {}).each_value do |scope| + (scope[:tree] || []).each { |node| gen.generate_statement(node) } end emitter end diff --git a/sim_gen/ExecEngines/naive_interpreter.rb b/sim_gen/ExecEngines/naive_interpreter.rb index ae00151..7aff60a 100644 --- a/sim_gen/ExecEngines/naive_interpreter.rb +++ b/sim_gen/ExecEngines/naive_interpreter.rb @@ -33,12 +33,8 @@ module TranslationUnit def map_operands(insn) operands = {} - cnt = 0 - insn[:map][:tree].each do |node| - if node[:name] == :new_var && !node[:attrs].nil? && node[:attrs].include?(:op) - operands[node[:oprnds][0][:name]] = "insn.operand#{cnt}" - cnt += 1 - end + (insn[:operand_list] || []).each_with_index do |name, idx| + operands[name] = "insn.operand#{idx}" end operands[:pc] = 'cpu.getPC()' operands diff --git a/sim_gen/ISA/isa.rb b/sim_gen/ISA/isa.rb index 4f4b830..e50683f 100644 --- a/sim_gen/ISA/isa.rb +++ b/sim_gen/ISA/isa.rb @@ -18,14 +18,20 @@ def find_max_operands(instructions) max_operands = 0 max_size = 0 instructions.each do |insn| - operands_count = 0 - insn[:map][:tree].each do |node| - if node[:name] == :new_var && !node[:attrs].nil? && node[:attrs].include?(:op) - operands_count += 1 - max_size = Utility.get_type(node[:oprnds][0][:type]).bitsize if Utility.get_type(node[:oprnds][0][:type]).bitsize > max_size - end - end - max_operands = operands_count if operands_count > max_operands + op_list = insn[:operand_list] || [] + max_operands = op_list.size if op_list.size > max_operands + op_map = insn[:operand_map] || {} + op_list.each do |name| + scope = op_map[name] + next unless scope + new_var_node = (scope[:tree] || []).find { |n| + n[:name] == :new_var && n[:attrs]&.include?(:op) + } + next unless new_var_node + type = new_var_node[:oprnds][0][:type] + bitsize = Utility.get_type(type).bitsize + max_size = bitsize if bitsize > max_size + end end [max_operands, max_size] end From 2f595d02a8b8cd62936f45ad3e5e875a70967bb1 Mon Sep 17 00:00:00 2001 From: uslstenn Date: Wed, 17 Jun 2026 12:20:44 +0300 Subject: [PATCH 4/7] [ADL, Target] Introduced Operand & OperandBuilder * Removed string-driven programming in operand definition * Operands was applied in "RISC-V/encoding.rb" description --- lib/ADL/base.rb | 2 +- lib/ADL/builder.rb | 87 +++++++++++++++++++++++++++++++++-- lib/Target/RISC-V/encoding.rb | 51 +++++++++++--------- 3 files changed, 113 insertions(+), 27 deletions(-) diff --git a/lib/ADL/base.rb b/lib/ADL/base.rb index 4eb5910..f709fe9 100644 --- a/lib/ADL/base.rb +++ b/lib/ADL/base.rb @@ -27,7 +27,7 @@ def self.state end # reset state - def siminfra_reset_module_state; @@instructions = []; end + def siminfra_reset_module_state; @@instructions = []; @@operands = []; end # mixin for global counter, function returns 0,1,2,.... module GlobalCounter diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index 81e8aaf..ce7fae9 100644 --- a/lib/ADL/builder.rb +++ b/lib/ADL/builder.rb @@ -34,6 +34,7 @@ def assert(condition, msg = nil); raise msg if !condition; end @@instructions = [] @@interface_functions = [] + @@operands = [] def self.interface_functions @@interface_functions @@ -78,6 +79,29 @@ def self.from_h(h) end end + class OperandInfo + attr_accessor :name, :type, :map_proc, :asm_str, :sem_proc + + def initialize(name, type = nil) + @name = name + @type = type + @map_proc = nil + @asm_str = nil + @sem_proc = nil + end + + def for(op_name) + template = self + info = OperandInfo.new(op_name, @type) + info.asm_str = @asm_str + info.sem_proc = @sem_proc + info.map_proc = proc { instance_exec(op_name, &template.map_proc) } + info + end + + alias_method :[], :for + end + class InstructionInfoBuilder include SimInfra @@ -128,6 +152,42 @@ def Instruction(name, &block) nil # only for debugging in IRB end + class OperandBuilder + include SimInfra + + def initialize(name, type = nil) + @info = OperandInfo.new(name, type) + end + + def map(type = nil, &block) + @info.type = type if type + @info.map_proc = block if block + end + + def asm(&block) + @info.asm_str = instance_eval(&block) if block + end + + def code(&block) + @info.map_proc = block if block + end + + def sem(&block) + @info.sem_proc = block if block + end + + attr_reader :info + end + + def Operand(name, type = nil, &block) + bldr = OperandBuilder.new(name, type) + bldr.instance_eval(&block) if block + @@operands << bldr.info + bldr.info + end + + module_function :Operand + class InterfaceBuilder include SimInfra @@ -237,13 +297,30 @@ def code(&block) def map(blocks) return if blocks.nil? || blocks.empty? - blocks.each do |name, type, code_str| - scope = Scope.new(nil) - @info.fields.each { |f| scope.method(f.value.name, f.value.type) } - scope.instance_eval(code_str) + + blocks.each do |block| + scope = build_scope(block) + name = operand_name(block) @info.operand_map[name] = scope end - @info.operand_list = blocks.map(&:first) + @info.operand_list = blocks.map { |b| operand_name(b) } + end + + private + + def operand_name(block) + block.is_a?(OperandInfo) ? block.name : block[0] + end + + def build_scope(block) + scope = Scope.new(nil) + @info.fields.each { |f| scope.method(f.value.name, f.value.type) } + if block.is_a?(OperandInfo) + scope.instance_eval(&block.map_proc) + else + scope.instance_eval(block[2]) + end + scope end def asm(&block) diff --git a/lib/Target/RISC-V/encoding.rb b/lib/Target/RISC-V/encoding.rb index 3214a0b..ba77af3 100644 --- a/lib/Target/RISC-V/encoding.rb +++ b/lib/Target/RISC-V/encoding.rb @@ -1,32 +1,41 @@ require_relative "../../ADL/base" +require_relative "../../ADL/builder" module SimInfra - def u_imm(imm) - return imm, :s32, "let :#{imm}, [:op], :s32, f_#{imm}.s << 12" + XReg = Operand(:XReg, :r32) do + map { |name| let name, :XRegs, [:op], :r32, send("f_#{name}") } end - def i_imm(imm) - return imm, :s32, "let :#{imm}, [:op], :s32, f_#{imm}.s32" + IImm = Operand(:IImm, :s32) do + map { |name| let name, [:op], :s32, send("f_#{name}").s32 } end - def is_imm(imm) - return imm, :s32, "let :#{imm}, [:op], :s32, f_imm4_0" + UImm = Operand(:UImm, :s32) do + map { |name| let name, [:op], :s32, (send("f_#{name}").s << 12) } end - def j_imm(imm) - return imm, :s32, "let :#{imm}, [:op], :s32, (f_imm20.b21 << 20 | f_imm19_12.b21 << 12 | f_imm11.b21 << 11 | f_imm10_1.b21 << 1).s32" + IsImm = Operand(:IsImm, :s32) do + map { |name| let name, [:op], :s32, f_imm4_0 } end - def b_imm(imm) - return imm, :s32, "let :#{imm}, [:op], :s32, (f_imm12.b13 << 12 | f_imm11.b13 << 11 | f_imm10_5.b13 << 5 | f_imm4_1.b13 << 1).s32" + JImm = Operand(:JImm, :s32) do + map { |name| + let name, [:op], :s32, + (f_imm20.b21 << 20 | f_imm19_12.b21 << 12 | f_imm11.b21 << 11 | f_imm10_1.b21 << 1).s32 + } end - def s_imm(imm) - return imm, :s32, "let :#{imm}, [:op], :s32, (f_imm11_5.b12 << 5 | f_imm4_0.b12).s32" + BImm = Operand(:BImm, :s32) do + map { |name| + let name, [:op], :s32, + (f_imm12.b13 << 12 | f_imm11.b13 << 11 | f_imm10_5.b13 << 5 | f_imm4_1.b13 << 1).s32 + } end - def xreg(name) - return name, :r32, "let :#{name}, :XRegs, [:op], :r32, f_#{name}" + SImm = Operand(:SImm, :s32) do + map { |name| + let name, [:op], :s32, (f_imm11_5.b12 << 5 | f_imm4_0.b12).s32 + } end end @@ -36,7 +45,7 @@ def format_u(opcode) field(:f_opcode, 6, 0, opcode), field(:f_rd, 11, 7), field(:f_imm, 31, 12), - ], xreg(:rd), u_imm(:imm) + ], XReg[:rd], UImm[:imm] end def format_r(opcode, funct3, funct7) @@ -47,7 +56,7 @@ def format_r(opcode, funct3, funct7) field(:f_rs1, 19, 15), field(:f_rs2, 24, 20), field(:f_funct7, 31, 25, funct7), - ], xreg(:rs2), xreg(:rs1), xreg(:rd) + ], XReg[:rs2], XReg[:rs1], XReg[:rd] end def format_i(opcode, funct3) @@ -57,7 +66,7 @@ def format_i(opcode, funct3) field(:f_funct3, 14, 12, funct3), field(:f_rs1, 19, 15), field(:f_imm, 31, 20), - ], i_imm(:imm), xreg(:rs1), xreg(:rd) + ], IImm[:imm], XReg[:rs1], XReg[:rd] end def format_i_shift(opcode, func3, funct7) @@ -68,7 +77,7 @@ def format_i_shift(opcode, func3, funct7) field(:f_rs1, 19, 15), field(:f_imm11_5, 31, 25, funct7), field(:f_imm4_0, 24, 20), - ], is_imm(:imm), xreg(:rs1), xreg(:rd) + ], IsImm[:imm], XReg[:rs1], XReg[:rd] end def format_b(opcode, funct3) @@ -81,7 +90,7 @@ def format_b(opcode, funct3) field(:f_imm10_5, 30, 25), field(:f_imm11, 7, 7), field(:f_imm12, 31, 31), - ], b_imm(:imm), xreg(:rs1), xreg(:rs2) + ], BImm[:imm], XReg[:rs1], XReg[:rs2] end def format_j(opcode) @@ -92,7 +101,7 @@ def format_j(opcode) field(:f_imm19_12, 19, 12), field(:f_imm11, 20, 20), field(:f_imm10_1, 30, 21), - ], j_imm(:imm), xreg(:rd) + ], JImm[:imm], XReg[:rd] end def format_s(opcode, func3) @@ -103,6 +112,6 @@ def format_s(opcode, func3) field(:f_rs1, 19, 15), field(:f_rs2, 24, 20), field(:f_imm11_5, 31, 25), - ], s_imm(:imm), xreg(:rs1), xreg(:rs2) + ], SImm[:imm], XReg[:rs1], XReg[:rs2] end end From 37ae35b8332a9016a2a4cecfe6b8b1c187c60da0 Mon Sep 17 00:00:00 2001 From: uslsteen Date: Sat, 24 Oct 2026 16:06:56 +0300 Subject: [PATCH 5/7] [infra] Formatted reverted --- lib/ADL/builder.rb | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index ce7fae9..c643cf9 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 = [] @@ -105,15 +105,16 @@ def for(op_name) 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 @@ -131,10 +132,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 @@ -198,7 +199,6 @@ def Function(name, output_types = [], input_types = []) def Interface(&blck) bldr = InterfaceBuilder.new() - bldr.instance_eval &blck end @@ -243,25 +243,25 @@ def self.from_h(h) @@regfiles = [] class RegisterFileBuilder - attr_reader :info - - def initialize(name) + attr_reader :info + + def initialize(name) @info = RegisterFileInfo.new(name) @info.regs = [] - end + end - def method_missing(name, *args) + 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..] : []) + 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}" + error "Unknown method #{name}" + end end - end - def zero = :zero - def pc = :pc + def zero = :zero + def pc = :pc end def RegisterFile(name, &block) From eaf875da02a4c59d533a5f01eaa20b8f7f4fdc73 Mon Sep 17 00:00:00 2001 From: uslsteen Date: Mon, 26 Oct 2026 10:07:29 +0300 Subject: [PATCH 6/7] Operand mapping refactored --- lib/ADL/builder.rb | 80 +++++++++++------------------------ lib/Target/RISC-V/encoding.rb | 47 ++++++++------------ 2 files changed, 42 insertions(+), 85 deletions(-) diff --git a/lib/ADL/builder.rb b/lib/ADL/builder.rb index c643cf9..0509888 100644 --- a/lib/ADL/builder.rb +++ b/lib/ADL/builder.rb @@ -34,7 +34,6 @@ def assert(condition, msg = nil); raise msg if !condition; end @@instructions = [] @@interface_functions = [] - @@operands = [] def self.interface_functions @@interface_functions @@ -42,13 +41,12 @@ def self.interface_functions class InstructionInfo attr_accessor :name, :fields, :frmt, :map, :code, :map_code_blocks, :asm_str, :feature, - :operand_map, :operand_list + :operand_map def initialize(name, feature) @name = name; @map_code_blocks = {} @feature = feature @operand_map = {} - @operand_list = [] end def to_h @@ -59,8 +57,7 @@ def to_h asm_str: @asm_str, code: @code.to_h, operand_map: @operand_map.transform_values(&:to_h), - operand_list: @operand_list, - feature: @feature, + operand_list: @operand_map.keys, } end @@ -73,29 +70,24 @@ def self.from_h(h) info.code.instance_variable_set(:@tree, h[:code][:tree].map { |s| IrStmt.from_h(s) }) if h[:operand_map] info.operand_map = h[:operand_map].transform_values { |v| Scope.from_h(v) } - info.operand_list = h[:operand_list] || info.operand_map.keys end info end end class OperandInfo - attr_accessor :name, :type, :map_proc, :asm_str, :sem_proc + attr_accessor :name, :type, :regset, :map_proc - def initialize(name, type = nil) + def initialize(name, type = nil, regset = nil) @name = name @type = type + @regset = regset @map_proc = nil - @asm_str = nil - @sem_proc = nil end def for(op_name) - template = self - info = OperandInfo.new(op_name, @type) - info.asm_str = @asm_str - info.sem_proc = @sem_proc - info.map_proc = proc { instance_exec(op_name, &template.map_proc) } + info = OperandInfo.new(op_name, @type, @regset) + info.map_proc = @map_proc info end @@ -135,11 +127,6 @@ def encoding(frmt, fields, *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 - end end attr_reader :info end @@ -156,34 +143,16 @@ def Instruction(name, &block) class OperandBuilder include SimInfra - def initialize(name, type = nil) - @info = OperandInfo.new(name, type) - end - - def map(type = nil, &block) - @info.type = type if type - @info.map_proc = block if block - end - - def asm(&block) - @info.asm_str = instance_eval(&block) if block - end - - def code(&block) - @info.map_proc = block if block - end - - def sem(&block) - @info.sem_proc = block if block + def initialize(name, type = nil, regset = nil) + @info = OperandInfo.new(name, type, regset) end attr_reader :info end - def Operand(name, type = nil, &block) - bldr = OperandBuilder.new(name, type) - bldr.instance_eval(&block) if block - @@operands << bldr.info + def Operand(name, type = nil, regset = nil, &block) + bldr = OperandBuilder.new(name, type, regset) + bldr.info.map_proc = block if block bldr.info end @@ -192,8 +161,8 @@ def Operand(name, type = nil, &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, output_types = [], input_types = [], attrs = []) + @@interface_functions << {name: name, return_types: output_types, argument_types: input_types, attrs: attrs} end end @@ -299,26 +268,27 @@ def map(blocks) return if blocks.nil? || blocks.empty? blocks.each do |block| - scope = build_scope(block) - name = operand_name(block) - @info.operand_map[name] = scope + @info.operand_map[block.name] = build_scope(block) end - @info.operand_list = blocks.map { |b| operand_name(b) } end private - def operand_name(block) - block.is_a?(OperandInfo) ? block.name : block[0] - end - def build_scope(block) scope = Scope.new(nil) @info.fields.each { |f| scope.method(f.value.name, f.value.type) } - if block.is_a?(OperandInfo) + op_name = block.name + value = if block.map_proc scope.instance_eval(&block.map_proc) + elsif block.regset + scope.send("f_#{op_name}") + else + raise "operand '#{op_name}' has no map rule" + end + if block.regset + scope.arlet(op_name, block.regset, [:op], block.type, value) else - scope.instance_eval(block[2]) + scope.alet(op_name, [:op], block.type, value) end scope end diff --git a/lib/Target/RISC-V/encoding.rb b/lib/Target/RISC-V/encoding.rb index ba77af3..61f31e1 100644 --- a/lib/Target/RISC-V/encoding.rb +++ b/lib/Target/RISC-V/encoding.rb @@ -2,41 +2,28 @@ require_relative "../../ADL/builder" module SimInfra - XReg = Operand(:XReg, :r32) do - map { |name| let name, :XRegs, [:op], :r32, send("f_#{name}") } - end + XReg = Operand(:XReg, :r32, :XRegs) - IImm = Operand(:IImm, :s32) do - map { |name| let name, [:op], :s32, send("f_#{name}").s32 } - end + IImm = Operand(:IImm, :s32) { f_imm.s32 } - UImm = Operand(:UImm, :s32) do - map { |name| let name, [:op], :s32, (send("f_#{name}").s << 12) } - end + UImm = Operand(:UImm, :s32) { f_imm.s32 << 12 } - IsImm = Operand(:IsImm, :s32) do - map { |name| let name, [:op], :s32, f_imm4_0 } - end + IsImm = Operand(:IsImm, :s32) { f_imm4_0 } - JImm = Operand(:JImm, :s32) do - map { |name| - let name, [:op], :s32, - (f_imm20.b21 << 20 | f_imm19_12.b21 << 12 | f_imm11.b21 << 11 | f_imm10_1.b21 << 1).s32 - } - end + JImm = Operand(:JImm, :s32) { + # imm[20] ← word[31], imm[19:12] ← word[19:12], imm[11] ← word[20], imm[10:1] ← word[30:21] + f_imm20.s32 << 20 | f_imm19_12.u32 << 12 | f_imm11.u32 << 11 | f_imm10_1.u32 << 1 + } - BImm = Operand(:BImm, :s32) do - map { |name| - let name, [:op], :s32, - (f_imm12.b13 << 12 | f_imm11.b13 << 11 | f_imm10_5.b13 << 5 | f_imm4_1.b13 << 1).s32 - } - end + BImm = Operand(:BImm, :s32) { + # imm[12] ← word[31], imm[11] ← word[7], imm[10:5] ← word[30:25], imm[4:1] ← word[11:8] + f_imm12.s32 << 12 | f_imm11.u32 << 11 | f_imm10_5.u32 << 5 | f_imm4_1.u32 << 1 + } - SImm = Operand(:SImm, :s32) do - map { |name| - let name, [:op], :s32, (f_imm11_5.b12 << 5 | f_imm4_0.b12).s32 - } - end + SImm = Operand(:SImm, :s32) { + # imm[11:5] ← word[31:25], imm[4:0] ← word[11:7] + f_imm11_5.s32 << 5 | f_imm4_0.u32 + } end module SimInfra @@ -107,7 +94,7 @@ def format_j(opcode) def format_s(opcode, func3) return :S, [ field(:f_opcode, 6, 0, opcode), - field(:func3, 14, 12, func3), + field(:f_func3, 14, 12, func3), field(:f_imm4_0, 11, 7), field(:f_rs1, 19, 15), field(:f_rs2, 24, 20), From f318f9d567c06a422471283e1a33e724e1aa9bef Mon Sep 17 00:00:00 2001 From: uslsteen Date: Tue, 27 Oct 2026 15:55:07 +0300 Subject: [PATCH 7/7] [RISC-V} Immediate layout explanation (cherry picked from commit 6075e4efe87180a3cf1b23179818f497fa2c218c) --- lib/Target/RISC-V/encoding.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/Target/RISC-V/encoding.rb b/lib/Target/RISC-V/encoding.rb index 61f31e1..97fd69f 100644 --- a/lib/Target/RISC-V/encoding.rb +++ b/lib/Target/RISC-V/encoding.rb @@ -73,10 +73,10 @@ def format_b(opcode, funct3) field(:f_funct3, 14, 12, funct3), field(:f_rs1, 19, 15), field(:f_rs2, 24, 20), - field(:f_imm4_1, 11, 8), - field(:f_imm10_5, 30, 25), - field(:f_imm11, 7, 7), - field(:f_imm12, 31, 31), + field(:f_imm4_1, 11, 8), # → imm[4:1] + field(:f_imm10_5, 30, 25), # → imm[10:5] + field(:f_imm11, 7, 7), # → imm[11] + field(:f_imm12, 31, 31), # → imm[12] ], BImm[:imm], XReg[:rs1], XReg[:rs2] end @@ -84,10 +84,10 @@ def format_j(opcode) return :J, [ field(:f_opcode, 6, 0, opcode), field(:f_rd, 11, 7), - field(:f_imm20, 31, 31), - field(:f_imm19_12, 19, 12), - field(:f_imm11, 20, 20), - field(:f_imm10_1, 30, 21), + field(:f_imm20, 31, 31), # → imm[20] + field(:f_imm19_12, 19, 12), # → imm[19:12] + field(:f_imm11, 20, 20), # → imm[11] + field(:f_imm10_1, 30, 21), # → imm[10:1] ], JImm[:imm], XReg[:rd] end @@ -95,10 +95,10 @@ def format_s(opcode, func3) return :S, [ field(:f_opcode, 6, 0, opcode), field(:f_func3, 14, 12, func3), - field(:f_imm4_0, 11, 7), + field(:f_imm4_0, 11, 7), # → imm[4:0] field(:f_rs1, 19, 15), field(:f_rs2, 24, 20), - field(:f_imm11_5, 31, 25), + field(:f_imm11_5, 31, 25), # → imm[11:5] ], SImm[:imm], XReg[:rs1], XReg[:rs2] end end