diff --git a/src/spec/index.ts b/src/spec/index.ts index cd61d3c..dbda889 100644 --- a/src/spec/index.ts +++ b/src/spec/index.ts @@ -1,13 +1,17 @@ import assert from 'assert'; import { ChildProcessByStdio, spawn } from 'child_process'; +import crypto from 'crypto'; import * as fs from "fs"; import * as path from 'path'; import { createInterface } from 'readline'; import { Readable, Writable } from 'stream'; import { promisify } from "util"; import specTemplate from '../../assets/specTemplate.cfg'; +import { sw64TargetOptions } from '../commands/compiler.js'; import { RunCPUOptions, runcpuOptions } from '../commands/spec.js'; -import { SPECBenchData, benchpath, buildpath, exepath } from './benchData.js'; +import * as sunway from '../sunway.js'; +import { cflangLibs, toolchain, ToolchainSuite } from '../toolchain/index.js'; +import { benchpath, buildpath, exepath, SPECBenchData } from './benchData.js'; @@ -242,3 +246,131 @@ export async function spawnSPECWithID( ...runcpuConfig, }), { env: spec.getEnvironment() }); } + +interface SPECRunOptions { + compilerPrefix: string; + compilerSuite: 'llvm' | 'gcc'; + workload?: 'test' | 'train' | 'ref'; + optimizeProfile: 'O2' | 'base' | 'openmp'; + allowMisaligned?: boolean; + spec: string; + output: string; + platform?: '8a' | '6b' | 'host'; + benchmarks?: string[]; + action?: 'build' | 'buildstep' | 'validate' | 'runsetup'; + buildType?: 'nobuild' | 'rebuild'; + simd: boolean; +} + +export async function runSPEC({ + compilerPrefix, + compilerSuite, + workload = 'ref', + optimizeProfile, + allowMisaligned = false, + spec, + output, + platform = 'host', + benchmarks = ['intspeed', 'fpspeed'], + action = 'validate', + buildType = 'rebuild', + simd +}: SPECRunOptions) { + // Determine platform configuration + const sunwayGeneration = platform === "host" + ? sunway.getHostGeneration() + : platform as sunway.SunwayGeneration; + + const sysrootFlag = sunwayGeneration === "6b" + ? ["--sysroot", "/usr/sw/standard-830-6b-test/"] + : []; + + // Generate unique ID for this run + const uuid = crypto.randomUUID(); + const prefix = path.resolve(compilerPrefix); + + // Define optimization profiles + const optimizeProfiles = { + base: [ + "-O3", + "-flto=thin", + ], + openmp: [ + "-O3", + "-flto=thin", + "-DSPEC_OPENMP", + "-fopenmp", + ], + O2: [ + "-O2", + ] + }; + + // Select optimizations based on profile + const optimizeFlags = optimizeProfiles[optimizeProfile as keyof typeof optimizeProfiles]; + + // Create SPEC process runner + const specInstance = mkSPEC(path.resolve(spec)); + + // Handle misaligned memory access flag + const sw64UnalignedFlag = "-sw64-allows-misaligned-memory-accesses"; + + // Add special flags for specific optimizations + function getSpecialFlags() { + if (optimizeProfile === "base") { + return [ + "648.exchange2_s:", + " EXTRA_OPTIMIZE = -mllvm -enable-ipsccp-pass", + " EXTRA_LDFLAGS = -Wl,-mllvm,-enable-ipsccp-pass", + ].join("\n"); + } + return ""; + } + + // Spawn SPEC process with configuration + const specProc = await spawnSPECWithID( + specInstance, + { + optimize: [ + ...optimizeFlags, + ...(allowMisaligned ? ["-mllvm", sw64UnalignedFlag] : []), + ...sw64TargetOptions({ simd }), + ...sysrootFlag, + ...(compilerSuite === "llvm" ? [sunway.mcpu(sunwayGeneration)] : []), + ], + ldflags: [ + `-L${path.resolve(prefix, 'lib')}`, + ...optimizeFlags, + "-fuse-ld=lld", + '-static', + ...sysrootFlag, + ...(["base", "openmp"].includes(optimizeProfile) + ? [ + ...(simd ? ["-Wl,-plugin-opt,-mattr=+simd"] : []), + ...(allowMisaligned ? [`-Wl,-plugin-opt,${sw64UnalignedFlag}`] : []), + ...(sunwayGeneration === "8a" ? ["-Wl,-plugin-opt,-mattr=+core4"] : []), + ] + : [] + ), + ], + compilerPaths: toolchain(compilerPrefix, compilerSuite as ToolchainSuite), + libs: compilerSuite === "llvm" ? cflangLibs(prefix) : [], + specialFlags: getSpecialFlags(), + openmp: { + threads: optimizeProfile === "openmp" ? 64 : 1, + } + }, + { + setprocgroup: true, + workload: workload as RunCPUOptions["workload"], + buildType: buildType as RunCPUOptions["buildType"], + benchmarks: benchmarks as RunCPUOptions["benchmarks"], + action: action as RunCPUOptions["action"], + }, + output, + uuid + ); + + // Get and return performance ratios + return getBaseRatios(specProc); +}