Skip to content

Commit f993dfd

Browse files
committed
Zvame: rename suffixes (1d→ew, row/col), add scalar (.ew.x.) variants and elementwise mul instructions
1 parent 53125f5 commit f993dfd

122 files changed

Lines changed: 5483 additions & 552 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/regress.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ jobs:
366366
cfg:
367367
- _
368368
- rv32
369-
regress-test-inst-encodings:
369+
regress-test-db-integrity:
370370
runs-on: ubuntu-latest
371371
steps:
372372
- name: Clone Github Repo Action
@@ -375,6 +375,8 @@ jobs:
375375
uses: "./.github/actions/mise-setup"
376376
- name: Checking for conflicts in instruction encodings
377377
run: "./do test:inst_encodings"
378+
- name: Checking register file enum_orders are valid
379+
run: "./do test:register_file_enum_orders"
378380
regress-gen-isa-manual:
379381
runs-on: ubuntu-latest
380382
steps:
@@ -857,7 +859,7 @@ jobs:
857859
- regress-ext-explorer
858860
- regress-idl-typecheck-smoke
859861
- regress-idl-typecheck-other
860-
- regress-test-inst-encodings
862+
- regress-test-db-integrity
861863
- regress-gen-isa-manual
862864
- regress-gen-instruction-appendix
863865
- regress-cfg-manual

Rakefile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,34 @@ namespace :test do
209209
Udb.logger.info "Encoding test PASSED"
210210
end
211211

212+
desc "Check that register file enum_orders are unique, contiguous, and start at 1"
213+
task :register_file_enum_orders do
214+
Udb.logger.info "Checking register file enum_orders..."
215+
216+
cfg_arch = $resolver.cfg_arch_for("_")
217+
ordered = cfg_arch.register_files.select(&:enum_order).sort_by(&:enum_order)
218+
219+
failed = T.let(false, T::Boolean)
220+
221+
orders = ordered.map(&:enum_order)
222+
if orders.uniq.size != orders.size
223+
Udb.logger.error "Duplicate enum_order values: #{orders.tally.select { |_, n| n > 1 }}"
224+
failed = true
225+
end
226+
227+
unless orders == (1..orders.size).to_a
228+
Udb.logger.error "enum_orders must be contiguous starting at 1; got: #{orders.inspect}"
229+
failed = true
230+
end
231+
232+
if failed
233+
Udb.logger.error "register_file_enum_orders test FAILED"
234+
exit 1
235+
end
236+
237+
Udb.logger.info "register_file_enum_orders test PASSED"
238+
end
239+
212240
desc "Check that CSR definitions in the DB are consistent and do not conflict"
213241
task :csrs do
214242
print "Checking for conflicts in CSRs.."

backends/cpp_hart_gen/cpp/include/udb/inst.hpp

Lines changed: 1 addition & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -3,156 +3,10 @@
33
#include "udb/bits.hpp"
44
#include "udb/bitfield.hpp"
55
#include "udb/pool_alloc.hpp"
6+
#include "udb/reg.hxx"
67

78
namespace udb {
89

9-
class Reg {
10-
public:
11-
enum Enum {
12-
X0 = 0,
13-
X1 = 1,
14-
X2 = 2,
15-
X3 = 3,
16-
X4 = 4,
17-
X5 = 5,
18-
X6 = 6,
19-
X7 = 7,
20-
X8 = 8,
21-
X9 = 9,
22-
X10 = 10,
23-
X11 = 11,
24-
X12 = 12,
25-
X13 = 13,
26-
X14 = 14,
27-
X15 = 15,
28-
X16 = 16,
29-
X17 = 17,
30-
X18 = 18,
31-
X19 = 19,
32-
X20 = 20,
33-
X21 = 21,
34-
X22 = 22,
35-
X23 = 23,
36-
X24 = 24,
37-
X25 = 25,
38-
X26 = 26,
39-
X27 = 27,
40-
X28 = 28,
41-
X29 = 29,
42-
X30 = 30,
43-
X31 = 31,
44-
F0 = 32,
45-
F1 = 33,
46-
F2 = 34,
47-
F3 = 35,
48-
F4 = 36,
49-
F5 = 37,
50-
F6 = 38,
51-
F7 = 39,
52-
F8 = 40,
53-
F9 = 41,
54-
F10 = 42,
55-
F11 = 43,
56-
F12 = 44,
57-
F13 = 45,
58-
F14 = 46,
59-
F15 = 47,
60-
F16 = 48,
61-
F17 = 49,
62-
F18 = 50,
63-
F19 = 51,
64-
F20 = 52,
65-
F21 = 53,
66-
F22 = 54,
67-
F23 = 55,
68-
F24 = 56,
69-
F25 = 57,
70-
F26 = 58,
71-
F27 = 59,
72-
F28 = 60,
73-
F29 = 61,
74-
F30 = 62,
75-
F31 = 63,
76-
V0 = 64,
77-
V1 = 65,
78-
V2 = 66,
79-
V3 = 67,
80-
V4 = 68,
81-
V5 = 69,
82-
V6 = 70,
83-
V7 = 71,
84-
V8 = 72,
85-
V9 = 73,
86-
V10 = 74,
87-
V11 = 75,
88-
V12 = 76,
89-
V13 = 77,
90-
V14 = 78,
91-
V15 = 79,
92-
V16 = 80,
93-
V17 = 81,
94-
V18 = 82,
95-
V19 = 83,
96-
V20 = 84,
97-
V21 = 85,
98-
V22 = 86,
99-
V23 = 87,
100-
V24 = 88,
101-
V25 = 89,
102-
V26 = 90,
103-
V27 = 91,
104-
V28 = 92,
105-
V29 = 93,
106-
V30 = 94,
107-
V31 = 95,
108-
INVALID = 96
109-
};
110-
111-
Reg(Enum r) : m_reg(r) {}
112-
Reg(uint64_t r, bool is_fp = false) : m_reg(Enum(is_fp ? r + 32 : r)) {}
113-
114-
template <typename BitsClass>
115-
requires (BitsClass::IsABits)
116-
Reg(const BitsClass& r, bool is_fp = false) : m_reg(Enum(is_fp ? r.get() + 32 : r.get())) {}
117-
118-
template <typename T>
119-
static Reg from_rf_index(T idx, uint64_t base) {
120-
if constexpr (requires { T::IsABits; }) {
121-
return Reg(Enum(idx.get() + base));
122-
} else {
123-
return Reg(Enum(static_cast<uint64_t>(idx) + base));
124-
}
125-
}
126-
127-
operator Enum() const { return m_reg; }
128-
bool operator==(const Reg &other) const { return m_reg == other.m_reg; }
129-
bool operator==(Enum other) const { return m_reg == other; }
130-
std::ostream &operator<<(std::ostream &o) const {
131-
o << to_string();
132-
return o;
133-
}
134-
135-
bool is_int() const { return m_reg <= X31; }
136-
bool is_fp() const { return m_reg >= F0 && m_reg <= F31; }
137-
bool is_vec() const { return m_reg >= V0 && m_reg <= V31; }
138-
139-
uint64_t get_num() const {
140-
uint64_t num = static_cast<uint64_t>(m_reg);
141-
if (m_reg <= X31) return num;
142-
if (m_reg <= F31) return num - 32u; // NOLINT
143-
return num - 64u; // V // NOLINT
144-
}
145-
146-
std::string to_string(uint64_t size = 64) const {
147-
if (is_fp()) return "f" + std::to_string(get_num());
148-
if (is_vec()) return "v" + std::to_string(get_num());
149-
return "x" + std::to_string(get_num());
150-
}
151-
152-
private:
153-
Enum m_reg = INVALID;
154-
};
155-
15610
class InstBase {
15711
public:
15812
InstBase() = default;

backends/cpp_hart_gen/lib/decode_tree.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def construct_decode_tree(tree, xlen, cur_range, test: false)
161161
if done_insts.empty? && !in_progress_groups.empty?
162162
# everything is still in an opcode, so grow the range and try again
163163
next_range = (cur_range.first..cur_range.last + 1)
164-
next_range_out_of_bounds = in_progress_groups.any? { |val, group| group.size > 1 && group.any? { |inst| inst.max_encoding_width <= next_range.last } }
164+
next_range_out_of_bounds = in_progress_groups.any? { |val, group| group.any? { |inst| inst.max_encoding_width <= next_range.last } }
165165
# puts "All insts have opcode at #{cur_range}, trying #{next_range}..."
166166
if next_range_out_of_bounds || tree.opcode_bit?(cur_range.last + 1) || (construct_decode_tree(tree, xlen, next_range, test: true) == false)
167167
# next bit goes too far, so this is the endpoint

backends/cpp_hart_gen/lib/template_helpers.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,18 @@ def rf_floating_point?(rf_name)
184184
end
185185

186186
# Returns the base offset into udb::Reg::Enum for the named register file.
187-
# Must match the enum layout in backends/cpp_hart_gen/cpp/include/udb/inst.hpp.
188-
RF_ENUM_BASES = { "X" => 0, "F" => 32, "V" => 64 }.freeze
187+
# Computed from enum_order and register counts defined in the register file YAMLs.
188+
# Must stay consistent with the enum layout generated by backends/cpp_hart_gen/templates/reg.hxx.erb.
189189
def rf_enum_base(rf_name)
190-
RF_ENUM_BASES.fetch(rf_name) { raise "No Reg::Enum base defined for register file '#{rf_name}'" }
190+
rf = cfg_arch.register_file(rf_name)
191+
raise "Unknown register file '#{rf_name}'" unless rf
192+
193+
order = rf.enum_order
194+
raise "No enum_order defined in register file '#{rf_name}'" unless order
195+
196+
cfg_arch.register_files
197+
.select { |other| other.enum_order && other.enum_order < order }
198+
.sum { |other| other.registers.length }
191199
end
192200

193201
# All register files defined for this architecture.

backends/cpp_hart_gen/tasks.rake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ namespace :gen do
296296
Rake::Task["#{CPP_HART_GEN_DST}/#{build_name}/CMakeLists.txt"].invoke
297297

298298
generated_files = []
299+
generated_files << "#{CPP_HART_GEN_DST}/#{build_name}/include/udb/reg.hxx"
299300
generated_files << "#{CPP_HART_GEN_DST}/#{build_name}/include/udb/hart_factory.hxx"
300301
generated_files << "#{CPP_HART_GEN_DST}/#{build_name}/include/udb/db_data.hxx"
301302
generated_files << "#{CPP_HART_GEN_DST}/#{build_name}/src/db_data.cxx"
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#pragma once
2+
// Generated from register file YAML definitions (enum_order field).
3+
// Do not edit manually — update spec/std/isa/register_file/*.yaml instead.
4+
5+
#include <cstdint>
6+
#include <ostream>
7+
#include <string>
8+
9+
namespace udb {
10+
11+
class Reg {
12+
public:
13+
enum Enum {
14+
<%- rfs = cfg_arch.register_files.select(&:enum_order).sort_by(&:enum_order)
15+
base = 0
16+
rf_ranges = {}
17+
rfs.each do |rf|
18+
rf_first = base
19+
rf.registers.each_with_index do |_reg, idx| -%>
20+
<%= rf.name %><%= idx %> = <%= base + idx %>,
21+
<%- end
22+
rf_ranges[rf.name] = { first: rf_first, last: base + rf.registers.length - 1 }
23+
base += rf.registers.length
24+
end -%>
25+
INVALID = <%= base %>
26+
};
27+
28+
Reg(Enum r) : m_reg(r) {}
29+
Reg(uint64_t r, bool is_fp = false) : m_reg(Enum(is_fp ? r + static_cast<uint64_t>(F0) : r)) {}
30+
31+
template <typename BitsClass>
32+
requires(BitsClass::IsABits)
33+
Reg(const BitsClass& r, bool is_fp = false) : m_reg(Enum(is_fp ? r.get() + static_cast<uint64_t>(F0) : r.get())) {}
34+
35+
template <typename T>
36+
static Reg from_rf_index(T idx, uint64_t base) {
37+
if constexpr (requires { T::IsABits; }) {
38+
return Reg(Enum(idx.get() + base));
39+
} else {
40+
return Reg(Enum(static_cast<uint64_t>(idx) + base));
41+
}
42+
}
43+
44+
operator Enum() const { return m_reg; }
45+
bool operator==(const Reg& other) const { return m_reg == other.m_reg; }
46+
bool operator==(Enum other) const { return m_reg == other; }
47+
std::ostream& operator<<(std::ostream& o) const {
48+
o << to_string();
49+
return o;
50+
}
51+
52+
<%- rfs.group_by(&:register_class).each do |rc, files| -%>
53+
bool is_<%= rc %>() const {
54+
return <%- files.each_with_index do |rf, i| -%><%= i > 0 ? "\n || " : "" %>(m_reg >= <%= rf.name %>0 && m_reg <= <%= rf.name %><%= rf.registers.length - 1 %>)<%- end -%>;
55+
}
56+
<%- end -%>
57+
bool is_int() const { return is_general_purpose(); }
58+
bool is_fp() const { return is_floating_point(); }
59+
bool is_vec() const { return is_vector(); }
60+
61+
uint64_t get_num() const {
62+
uint64_t num = static_cast<uint64_t>(m_reg);
63+
<%- rfs.each do |rf| -%>
64+
if (m_reg >= <%= rf.name %>0 && m_reg <= <%= rf.name %><%= rf.registers.length - 1 %>) return num - <%= rf_ranges[rf.name][:first] %>u; // NOLINT
65+
<%- end -%>
66+
return num;
67+
}
68+
69+
std::string to_string(uint64_t size = 64) const {
70+
<%- rfs.each do |rf| -%>
71+
if (m_reg >= <%= rf.name %>0 && m_reg <= <%= rf.name %><%= rf.registers.length - 1 %>) return "<%= rf.name.downcase %>" + std::to_string(get_num());
72+
<%- end -%>
73+
return "invalid";
74+
}
75+
76+
private:
77+
Enum m_reg = INVALID;
78+
};
79+
80+
} // namespace udb

0 commit comments

Comments
 (0)