|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <stdint.h> |
|
#include <immintrin.h> |
|
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION |
|
#include "stb_image_write.h" |
|
|
|
#include "encoding.out.h" |
|
/* |
|
* This "encoding.out.h" was auto-generated by running |
|
* 'PYTHONPATH=src python -m riscv_opcodes -c "rv*"' in |
|
* https://github.com/riscv/riscv-opcodes (a2766fd) |
|
* with the following patch applied: |
|
* diff --git a/src/riscv_opcodes/c_utils.py b/src/riscv_opcodes/c_utils.py |
|
* index 198a37f..236fe6f 100644 |
|
* --- a/src/riscv_opcodes/c_utils.py |
|
* +++ b/src/riscv_opcodes/c_utils.py |
|
* @@ -15,2 +15,3 @@ def make_c(instr_dict: InstrDict): |
|
* declare_insn_str = "" |
|
* + myexts = set() |
|
* for i in instr_dict: |
|
* @@ -22,3 +23,10 @@ def make_c(instr_dict: InstrDict): |
|
* ) |
|
* - declare_insn_str += f'DECLARE_INSN({i.replace(".","_")}, MATCH_{i.upper().replace(".","_")}, MASK_{i.upper().replace(".","_")})\n' |
|
* + myexts.add(instr_dict[i]["extension"][0]) |
|
* + declare_insn_str += f'DECLARE_INSN(EXT_{instr_dict[i]["extension"][0]}, {i.replace(".","_")}, MATCH_{i.upper().replace(".","_")}, MASK_{i.upper().replace(".","_")})\n' |
|
* + ext_enum = "" |
|
* + ext_str = "" |
|
* + for e in myexts: |
|
* + ext_enum += ( f'EXT_{e},\n' ) |
|
* + ext_str += ( f'"{e}",') |
|
* + |
|
* |
|
* @@ -65,2 +73,7 @@ def make_c(instr_dict: InstrDict): |
|
* {mask_match_str} |
|
* +typedef enum Ext {{ |
|
* +EXT_NONE, |
|
* +{ext_enum}EXT_COUNT |
|
* +}} Ext; |
|
* +const char *ext2str[EXT_COUNT] = {{ {ext_str} }}; |
|
* {csr_names_str} |
|
*/ |
|
|
|
#define ARR_LEN(a) (sizeof (a) / sizeof *(a)) |
|
|
|
typedef struct ExtGroup { |
|
const char *name; |
|
Ext *exts; |
|
} ExtGroup; |
|
|
|
#define EXT_custom EXT_COUNT |
|
#define EXT_gt32b (EXT_COUNT+1) |
|
|
|
typedef struct Insn { uint32_t ext, match, mask; } Insn; |
|
Insn insns[] = { |
|
{EXT_custom, 0b1011011, 0b1011111 }, |
|
{EXT_custom, 0b0101011, 0b0111111 }, |
|
{EXT_gt32b, 0b0011111, 0b0011111 }, |
|
#define DECLARE_INSN(ext,name,match,mask) {ext, match, mask}, |
|
#include "encoding.out.h" |
|
#undef DECLARE_INSN |
|
}; |
|
|
|
#define SEL 1 // select between first and second image |
|
|
|
#if SEL == 1 |
|
static const uint32_t BG = 0xFF100408; |
|
static uint32_t colors[] = { 0x5F8E02, 0x002ECB, 0x1A95FF, }; |
|
static ExtGroup groups[] = { |
|
{ "16-bit", (Ext[]){ EXT_rv_c, EXT_rv64_c, EXT_rv_c_d, EXT_rv_zcb, EXT_rv64_zcb, 0 } }, |
|
{ "custom", (Ext[]){ EXT_custom, 0 } }, |
|
{ "32-bit", (Ext[]){ EXT_rv_i, EXT_rv64_i, EXT_rv_m, EXT_rv64_m, EXT_rv_zicond, EXT_rv_zicsr, EXT_rv_zifencei, EXT_rv_zknh, EXT_rv64_zknd, EXT_rv_zksed, EXT_rv_zksh, EXT_rv64_zkne, EXT_rv64_zknh, EXT_rv_zba, EXT_rv64_zba, EXT_rv_zbb, EXT_rv64_zbb, EXT_rv_zbs, EXT_rv64_zbs, EXT_rv_zbc, EXT_rv_zbkb, EXT_rv_zbkx, EXT_rv64_zbkb, EXT_rv_a, EXT_rv64_a, EXT_rv_zabha, EXT_rv_zabha_zacas, EXT_rv_zacas, EXT_rv64_zacas, EXT_rv_zawrs, EXT_rv_s, EXT_rv_sdext, EXT_rv_smrnmi, EXT_rv_ssctr, EXT_rv_svinval, EXT_rv_system, EXT_rv_h, EXT_rv64_h, EXT_rv_svinval_h, EXT_rv_zfbfmin, EXT_rv_zicbo, EXT_rv_zimop, EXT_rv_zfh_zfa, EXT_rv_zfh, EXT_rv64_zfh, EXT_rv_zfhmin, EXT_rv_d_zfhmin, EXT_rv_f, EXT_rv64_f, EXT_rv_f_zfa, EXT_rv_d, EXT_rv64_d, EXT_rv_d_zfa, EXT_rv_q, EXT_rv64_q, EXT_rv_q_zfa, EXT_rv64_q_zfa, EXT_rv_q_zfhmin, EXT_rv_v, EXT_rv_zvbb, EXT_rv_zvbc, EXT_rv_zvkg, EXT_rv_zvkned, EXT_rv_zvknha, EXT_rv_zvksed, EXT_rv_zvksh, EXT_rv_zvfbfmin, EXT_rv_zvfbfwma, 0 } }, |
|
}; |
|
#elif SEL == 2 |
|
|
|
static const uint32_t BG = 0xFF332827; |
|
static uint32_t colors[] = { 0xF8F8F2, 0xEFD966, 0x5ACFDC, 0x1F97FD, 0xFF81AE, 0x7226F9, }; |
|
|
|
static ExtGroup groups[] = { |
|
{ "custom", (Ext[]){ EXT_custom, 0 } }, |
|
//{ "C", (Ext[]){ EXT_rv_c, EXT_rv64_c, EXT_rv_c_d, EXT_rv_zcb, EXT_rv64_zcb, 0 } }, |
|
{ "general", (Ext[]){ EXT_rv_i, EXT_rv64_i, EXT_rv_m, EXT_rv64_m, EXT_rv_zicond, EXT_rv_zicsr, EXT_rv_zifencei, EXT_rv_zknh, EXT_rv64_zknd, EXT_rv_zksed, EXT_rv_zksh, EXT_rv64_zkne, EXT_rv64_zknh, EXT_rv_zba, EXT_rv64_zba, EXT_rv_zbb, EXT_rv64_zbb, EXT_rv_zbs, EXT_rv64_zbs, EXT_rv_zbc, EXT_rv_zbkb, EXT_rv_zbkx, EXT_rv64_zbkb, EXT_rv_a, EXT_rv64_a, EXT_rv_zabha, EXT_rv_zabha_zacas, EXT_rv_zacas, EXT_rv64_zacas, EXT_rv_zawrs, 0 } }, |
|
{ "system", (Ext[]){ EXT_rv_zicsr, EXT_rv_zifencei, EXT_rv_s, EXT_rv_sdext, EXT_rv_smrnmi, EXT_rv_ssctr, EXT_rv_svinval, EXT_rv_system, EXT_rv_h, EXT_rv64_h, EXT_rv_svinval_h, EXT_rv_zicbo, EXT_rv_zimop, 0 } }, |
|
{ "FP", (Ext[]){ EXT_rv_zfh_zfa, EXT_rv_zfh, EXT_rv64_zfh, EXT_rv_zfhmin, EXT_rv_d_zfhmin, EXT_rv_f, EXT_rv64_f, EXT_rv_f_zfa, EXT_rv_d, EXT_rv64_d, EXT_rv_d_zfa, EXT_rv_q, EXT_rv64_q, EXT_rv_q_zfa, EXT_rv64_q_zfa, EXT_rv_q_zfhmin, EXT_rv_zfbfmin, 0 } }, |
|
{ "V", (Ext[]){ EXT_rv_v, EXT_rv_zvbb, EXT_rv_zvbc, EXT_rv_zvfbfmin, EXT_rv_zvfbfwma, 0 } }, |
|
{ "Zvk", (Ext[]){ EXT_rv_zvkg, EXT_rv_zvkned, EXT_rv_zvknha, EXT_rv_zvksed, EXT_rv_zvksh, 0 } }, |
|
|
|
}; |
|
#endif |
|
|
|
_Static_assert(ARR_LEN(colors) >= ARR_LEN(groups), "insufficient colors defined"); |
|
|
|
#if SEL == 1 |
|
#define WIDTH (1ull<<13) |
|
#elif SEL == 2 |
|
#define WIDTH (1ull<<11) |
|
#endif |
|
|
|
#include <immintrin.h> |
|
|
|
static uint32_t |
|
perm(uint32_t u) { |
|
// u = _pext_u32(u,0b11111111111100001111111001111111); |
|
u = (u & 0b1111111) | ((u>>2) & (0b1111111<<7)) | ((u>>6) & (0b111111111111<<14)); |
|
// reverse bits |
|
u = ((u >> 1) & 0x55555555) | ((u & 0x55555555) << 1); |
|
u = ((u >> 2) & 0x33333333) | ((u & 0x33333333) << 2); |
|
u = ((u >> 4) & 0x0F0F0F0F) | ((u & 0x0F0F0F0F) << 4); |
|
#if SEL == 1 |
|
u = __builtin_bswap32(u) >> 6; |
|
#elif SEL == 2 |
|
u = __builtin_bswap32(u)<<2 >> 10; |
|
#endif |
|
// interleave for morton code |
|
uint32_t x = _pext_u32(u, 0b01010101010101010101010101010101); |
|
uint32_t y = _pext_u32(u, 0b10101010101010101010101010101010); |
|
return (x+y*WIDTH) & (WIDTH*WIDTH-1); |
|
} |
|
|
|
int |
|
main(void) |
|
{ |
|
size_t total = 0; |
|
uint32_t *img = malloc(WIDTH*WIDTH * sizeof *img); |
|
for (size_t i = 0; i < WIDTH*WIDTH; ++i) |
|
img[i] = BG; |
|
|
|
for (size_t g = 0; g < ARR_LEN(groups); ++g) { |
|
uint32_t color = colors[g]; |
|
printf("%s:\t0x%08X\n", groups[g].name, color | 0xFF000000); |
|
for (Ext *e = groups[g].exts; *e; ++e) { |
|
for (size_t i = 0; i < ARR_LEN(insns); ++i) { |
|
if (insns[i].ext != *e) continue; |
|
uint32_t match = insns[i].match, mask = ~insns[i].mask; |
|
match = perm(match); mask = perm(mask); |
|
uint32_t cnt = 1ull << __builtin_popcount(mask); |
|
uint32_t opcode = 0; |
|
for (uint32_t c = 0; c < cnt; ++c) { |
|
++total; |
|
size_t idx = opcode & mask | match; |
|
uint32_t col = img[idx]; |
|
img[idx] = col != BG ? col : (color | 0xFF000000); |
|
opcode = (opcode | ~mask) + 1; |
|
} |
|
} |
|
} |
|
} |
|
printf("%zu\n", total); |
|
stbi_write_png("out.png", WIDTH, WIDTH, 4, img, WIDTH*4); |
|
return 0; |
|
} |
With instruction bits rearranged differently to make certain opcode patterns more visible, plus interpolating colors for representing encoding space utilization sub-pixel (https://gist.github.com/dzaima/645c92635c2717805b65b22d1d9222b0):
